/*
 * TagByteArray.cpp
 *
 *  Created on: 19 juin 2011
 *      Author: Pierrick Caillon <pierrick@megami.fr>
 */

#include "TagByteArray.h"
#include "TagInt.h"
#include <bits/functexcept.h>
#include <string.h>
#include <algorithm>

/* NAMEDTAG_H_ */
/* NAMEDTAG_H_ */
namespace NamedBinaryTag
{
TagByteArray::TagByteArray() :
	NamedTag(), length(0), data(NULL)
{
}

TagByteArray::~TagByteArray()
{
	if (data != NULL)
		delete[] data;
}

size_t TagByteArray::get_Length() const
{
	return this->length;
}

char TagByteArray::get_Item(size_t index) const throw ()
{
	if (index < this->length)
		return this->data[index];

	std::__throw_out_of_range(
			__N("TagByteArray::get_Item: subscript out of range."));
}
void TagByteArray::set_Value(char *value, size_t length)
{
	if (length == 0)
	{
		delete[] this->data;
		this->data = NULL;
		this->length = 0;
	}
	else if (this->length != length)
	{
		char *tempData = new char[length];
		memcpy(tempData, value, length);
		if (this->data != NULL)
			delete[] this->data;
		this->data = tempData;
		this->length = length;
	}
	else
	{
		memcpy(this->data, value, length);
	}
}

char *TagByteArray::get_Value() const
{
	return this->data;
}

void TagByteArray::set_Length(size_t length)
{
	if (length == 0)
	{
		delete[] this->data;
		this->data = NULL;
		this->length = 0;
	}
	else if (this->length != length)
	{
		char *tempData = new char[length];
		if (this->length < length)
			memset(tempData + this->length, 0, length - this->length);
		if (this->data != NULL)
		{
			memcpy(tempData, this->data, std::min(this->length, length));
			delete[] this->data;
		}
		this->data = tempData;
		this->length = length;
	}
}

void TagByteArray::Read(std::istream & input, bool ignoreName)
{
	NamedTag::Read(input, ignoreName);
	TagInt length;
	length.Read(input, true);
	this->length = length.get_Value();
	if (this->data != NULL)
		delete[] this->data;
	this->data = NULL;
	if (this->length > 0)
	{
		this->data = new char[this->length];
		input.read(this->data, this->length);
	}
}

void TagByteArray::Write(std::ostream & output, bool ignoreName) const
{
	NamedTag::Write(output, ignoreName);
	TagInt length;
	length.set_Value(this->length);
	length.Write(output, true);
	if (this->length > 0)
	{
		output.write(this->data, this->length);
	}
}

void TagByteArray::set_Item(char value, size_t index) throw ()
{
	if (index < this->length)
		this->data[index] = value;

	std::__throw_out_of_range(
			__N("TagByteArray::set_Item: subscript out of range."));
}
TagTypes TagByteArray::get_TagType() const
{
	return TAG_BYTEARRAY;
}

ITag *TagByteArray::clone() const
{
	return this->clone(NULL);
}

ITag *TagByteArray::clone(void *newRoot) const
{
	TagByteArray *copy = new TagByteArray(newRoot);
	copy->set_Value(this->data, this->length);
	return copy;
}

}
